/**
 * @Author: 鱿鱼溪学院
 * @Date: 2025-11-09
 * @Description: 管理员控制器
 * @FilePath: \jmd-ser-ts\app\controller\AdminController.ts
 */

import { Context } from 'koa'
import { AdminService } from '../service/AdminService'
import { ResponseUtil } from '../utils/ResponseUtil'
import { Admin } from '../model/Admin'
import { NotFoundException, BadRequestException } from '../exception'
import { Op } from 'sequelize'

// 导入集中管理的错误常量
import { ADMIN_ERRORS } from '../types/errors'

// 导入统一日志管理
import { Logger } from '../logger/Logger'

// 获取控制器专用logger
const logger = Logger.getControllerLogger('AdminController')

/**
 * 管理员控制器类
 * 处理管理员相关的HTTP请求
 */
export class AdminController {
  /**
   * 创建管理员
   * @param ctx Koa上下文对象
   * @body {username: string, password: string} 管理员信息
   * @returns {id: number, username: string, status: number} 管理员信息
   * @url POST /api/admin
   */
  public static async createAdmin(ctx: Context): Promise<void> {
    // 记录请求开始日志
    const requestBody = ctx.request.body || {}

    console.log(logger, 'logger 控制器专用logger')
    logger.info('创建管理员请求开始', {
      requestId: ctx.state.requestId,
      ip: ctx.ip,
      username: (requestBody as any).username || '未提供'
    })

    // 从请求体中获取管理员数据
    const adminData = (ctx.request.body || {}) as Partial<Admin>

    // 增强数据验证逻辑
    if (!adminData.username) {
      logger.error(`用户名验证失败：${ADMIN_ERRORS.USERNAME_REQUIRED}`, {
        requestId: ctx.state.requestId
      })
      throw new BadRequestException(ADMIN_ERRORS.USERNAME_REQUIRED)
    }

    if (!adminData.password) {
      logger.error(`密码验证失败：${ADMIN_ERRORS.PASSWORD_REQUIRED}`, {
        requestId: ctx.state.requestId
      })
      throw new BadRequestException(ADMIN_ERRORS.PASSWORD_REQUIRED)
    }

    // 验证用户名长度
    if (adminData.username.length < 3 || adminData.username.length > 50) {
      logger.error(`用户名验证失败：${ADMIN_ERRORS.USERNAME_LENGTH_INVALID}`, {
        requestId: ctx.state.requestId,
        username: adminData.username
      })
      throw new BadRequestException(ADMIN_ERRORS.USERNAME_LENGTH_INVALID)
    }

    // 验证密码强度（至少6位，包含字母和数字）
    if (adminData.password.length < 6) {
      logger.error(`密码验证失败：${ADMIN_ERRORS.PASSWORD_LENGTH_INVALID}`, {
        requestId: ctx.state.requestId
      })
      throw new BadRequestException(ADMIN_ERRORS.PASSWORD_LENGTH_INVALID)
    }

    const hasLetter = /[a-zA-Z]/.test(adminData.password)
    const hasNumber = /[0-9]/.test(adminData.password)
    if (!hasLetter || !hasNumber) {
      logger.error(`密码验证失败：${ADMIN_ERRORS.PASSWORD_STRENGTH_INVALID}`, {
        requestId: ctx.state.requestId
      })
      throw new BadRequestException(ADMIN_ERRORS.PASSWORD_STRENGTH_INVALID)
    }

    logger.info('管理员数据验证通过', {
      requestId: ctx.state.requestId,
      username: adminData.username
    })

    const admin = await AdminService.createAdmin(adminData)

    console.log('admin', admin.toJSON().username + '创建管理员成功')

    // 记录创建成功日志
    logger.info('管理员创建成功', {
      requestId: ctx.state.requestId,
      adminId: admin.id,
      username: admin.toJSON().username || '未知用户名'
    })

    // 创建成功，不返回密码信息
    const responseData = { ...admin.toJSON() }
    delete responseData.password

    ResponseUtil.success(ctx, '创建管理员成功', responseData, 201)
  }

  /**
   * 获取管理员详情
   * @param ctx Koa上下文对象
   */
  public static async getAdminDetail(ctx: Context): Promise<void> {
    // 复用getAdminById方法
    await this.getAdminById(ctx)
  }

  /**
   * 通过ID获取管理员
   * @param ctx Koa上下文对象
   */
  public static async getAdminById(ctx: Context): Promise<void> {
    try {
      const { id } = ctx.params
      const adminId = parseInt(id, 10)

      if (isNaN(adminId)) {
        throw new BadRequestException('无效的管理员ID')
      }

      const admin = await AdminService.getAdminById(adminId)

      if (!admin) {
        throw new NotFoundException('管理员不存在')
      }

      // 返回时隐藏密码
      const responseData = { ...admin.toJSON() }
      delete responseData.password

      ResponseUtil.success(ctx, '获取管理员详情成功', responseData)
    } catch (error: any) {
      throw error
    }
  }

  /**
   * 获取管理员列表
   * @param ctx Koa上下文对象
   */
  public static async getAdminList(ctx: Context): Promise<void> {
    try {
      // 获取查询参数
      const page = parseInt(ctx.query.page as string, 10) || 1
      console.log('page', ctx.query.page)

      const pageSize = parseInt(ctx.query.pageSize as string, 10) || 10

      console.log('pageSize', ctx.query.pageSize)

      const username = ctx.query.username as string
      console.log('username', username)

      const status = ctx.query.status
        ? parseInt(ctx.query.status as string, 10)
        : undefined
      console.log('status', status)

      // 构建查询条件
      const whereConditions: any = {}
      if (username) {
        // 对用户名进行模糊查询
        whereConditions.username = { [Op.like]: `%${username}%` }
        console.log(whereConditions.username, username)
      }
      if (status !== undefined) {
        whereConditions.status = status
      }

      return ResponseUtil.success(ctx, '查询条件', whereConditions)

      console.log('whereConditions', whereConditions)

      const { list, total } = await AdminService.getAdminList({
        page,
        pageSize,
        where: whereConditions
      })

      // 处理列表数据，隐藏密码
      const formattedList = list.map((admin) => {
        const adminData = admin.toJSON()
        delete adminData.password
        return adminData
      })

      ResponseUtil.paginated(
        ctx,
        formattedList,
        total,
        page,
        pageSize,
        '获取管理员列表成功'
      )
    } catch (error: any) {
      throw new NotFoundException(`获取管理员列表失败: ${error.message}`)
    }
  }

  /**
   * 更新管理员信息
   * @param ctx Koa上下文对象
   */
  public static async updateAdmin(ctx: Context): Promise<void> {
    try {
      const { id } = ctx.params
      const adminId = parseInt(id, 10)
      const updateData = (ctx.request as any).body as Partial<Admin>

      if (isNaN(adminId)) {
        throw new BadRequestException('无效的管理员ID')
      }

      const admin = await AdminService.updateAdmin(adminId, updateData)

      // 返回时隐藏密码
      const responseData = { ...admin.toJSON() }
      delete responseData.password

      ResponseUtil.success(ctx, '更新管理员信息成功', responseData)
    } catch (error: any) {
      throw error
    }
  }

  /**
   * 删除管理员
   * @param ctx Koa上下文对象
   */
  public static async deleteAdmin(ctx: Context): Promise<void> {
    try {
      const { id } = ctx.params
      const adminId = parseInt(id, 10)

      if (isNaN(adminId)) {
        throw new BadRequestException('无效的管理员ID')
      }

      await AdminService.deleteAdmin(adminId)

      ResponseUtil.success(ctx, '删除管理员成功')
    } catch (error: any) {
      throw error
    }
  }

  /**
   * 管理员登录
   * @param ctx Koa上下文对象
   */
  public static async login(ctx: Context): Promise<void> {
    try {
      const { username, password } = (ctx.request as any).body

      if (!username || !password) {
        throw new BadRequestException('用户名和密码不能为空')
      }

      // 获取客户端IP
      const clientIp = ctx.ip

      const loginResult = await AdminService.verifyLogin(username, password)

      if (!loginResult.success) {
        ResponseUtil.unauthorized(ctx, loginResult.message || '登录失败')
        return
      }

      if (loginResult.admin) {
        // 更新登录IP（这里应该在verifyLogin方法中处理，但为了演示，这里也可以更新）
        if (clientIp && loginResult.admin.last_login_ip !== clientIp) {
          await loginResult.admin.update({ last_login_ip: clientIp })
        }

        // 准备返回数据，隐藏密码
        const adminData = { ...loginResult.admin.toJSON() }
        delete adminData.password

        // 这里应该生成并返回token，简化处理
        const token = `mock_token_${Date.now()}`

        ResponseUtil.success(ctx, '登录成功', {
          admin: adminData,
          token
        })
      }
    } catch (error: any) {
      throw error
    }
  }

  /**
   * 更新管理员状态
   * @param ctx Koa上下文对象
   */
  public static async updateAdminStatus(ctx: Context): Promise<void> {
    try {
      const { id } = ctx.params
      const adminId = parseInt(id, 10)
      const { status } = (ctx.request as any).body

      if (isNaN(adminId) || status === undefined) {
        throw new BadRequestException('无效的参数')
      }

      const admin = await AdminService.updateAdmin(adminId, { status })

      // 返回时隐藏密码
      const responseData = { ...admin.toJSON() }
      delete responseData.password

      ResponseUtil.success(ctx, '更新管理员状态成功', responseData)
    } catch (error: any) {
      throw error
    }
  }
}
